/*
 * Shell.h
 *
 *  Created on:  May 29, 2009
 *      Author:  Zach Riggle A37627537
 *      Project: CSE410 Project 1
 */

#ifndef SHELL_H_
#define SHELL_H_

#include <vector>
#include <string>
#include <queue>

using namespace std;

/**
 * Shell class.  Provides the interface to the user, and retrieves user input.
 * Also handles backgrounded processes, and notifications to the user of
 * when these processes have completed.
 */
class ShellCommand;

class Shell {
public:
    Shell();
    Shell(string firstCommand);
    virtual ~Shell();

    /**
     * @return The output for the 'hist' command.
     */
    string getHistory();

    /**
     * @return The prompt, as it should be displayed to the user:
     * <# host:user>
     */
    string getPrompt();

    /**
     * Adds a command to the queue of commands to be executed.
     */
    void addCommand(string cmdToAdd);

    /**
     * @return The next command from the queue of commands to be executed.
     */
    string getNextCommand();

    /**
     * @return The PID of the process that is interfacing with the user.
     */
    pid_t getPromptPID();

    /**
     * @return The current users's username.
     */
    static string getUsername();

    /**
     * @return The current hostname
     */
    static string getHostname();

    /**
     * Enters the prompt loop, which will be exited when the user enters
     * the 'quit' command.
     */
    void prompt();

    /**
     * Executes all commands in the command queue.
     */
    void executeCommands();

    /**
     * Causes the shell to quit as soon as possible.
     */
    void quit();

    /**
     * Change the operating directory of the shell.
     */
    void changeShellDirectory(const char*);

protected:

    /**
     * Check to see if any other processes have called changeShellDirectory and
     * written to the pipe telling us to change the directory.
     */
    void checkChdir();

    friend class ShellCommand;

    // Save the prompt pid
    pid_t promptPid;

    // Print all completed background commands.
    void printCompletedBackgroundCommands();

    // Continue running?
    bool quitShell;

    // List of commands
    vector<string> commandHistory;
    queue<string>  commandsToExecute;

    // List of processes that have been backgrounded, and completed.
    int backgroundCounter;
    vector<ShellCommand*> backgroundedCommands;

    // Pipe used for communicating directly with spawned processes.
    // This is ONLY used to send the arguments of a 'cd' back to the main process.
    int shellPipe[2];
};

// Well, if I have to break one rule throughout this ENTIRE project, I'll make a global variable.
// But, since you can't initialize non-static values without calling a constructor (think Java),
// making it into a static-only class isn't really an option.
extern Shell shell;

#endif /* SHELL_H_ */
